/*
     Copyright 2007 Joseph M. Ferner

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using OpenServers.Net.Common.FileSystem;
using OpenServers.Net.FtpServer.State;

namespace OpenServers.Net.FtpServer.Command {
    /// <summary>
    ///     <para>
    ///         <b>RENAME TO (RNTO)</b><br/>
    ///         This command specifies the new pathname of the file
    ///         specified in the immediately preceding "rename from"
    ///         command.  Together the two commands cause a file to be
    ///         renamed.
    ///     </para>
    ///     <para>
    ///         <b>Format</b><br/>
    ///         <code>RNTO &lt;SP&gt; &lt;pathname&gt; &lt;CRLF&gt;</code>
    ///     </para>
    ///     <para>
    ///         <b>Success:</b>
    ///         <list type="bullet">
    ///             <item><term>250</term><description>Requested file action okay, completed.</description></item>
    ///         </list>
    ///     </para>
    ///     <para>
    ///         <b>Errors:</b>
    ///         <list type="bullet">
    ///             <item><term>421</term><description>Service not available, closing control connection.</description></item>
    ///             <item><term>500</term><description>Syntax error, command unrecognized.</description></item>
    ///             <item><term>501</term><description>Syntax error in parameters or arguments.</description></item>
    ///             <item><term>502</term><description>Command not implemented.</description></item>
    ///             <item><term>503</term><description>Bad sequence of commands.</description></item>
    ///             <item><term>530</term><description>Not logged in.</description></item>
    ///             <item><term>532</term><description>Need account for storing files.</description></item>
    ///             <item><term>553</term><description>Requested action not taken. File name not allowed.</description></item>
    ///         </list>
    ///     </para>
    /// </summary>
    public class RenameToCommand : BaseCommand {
        /// <summary>
        /// renames the file specifed in the rename from command.
        /// </summary>
        public override void PerformCommand(IFtpServer server, FtpState state, string arguments) {
            if (string.IsNullOrEmpty(arguments)) {
                state.Listener.Send(state, server.Messages.Get501());
            } else {
                string filePath = GetFilePath(state, arguments);
                if (state.LastRenameFrom == null) {
                    state.Listener.Send(state, server.Messages.Get503());
                } else {
                    IFileSystemObject fso;

                    if (state.LastRenameFrom is IFile) {
                        fso = server.FileSystem.GetFile(filePath);
                    } else if (state.LastRenameFrom is IDirectory) {
                        fso = server.FileSystem.GetDirectory(filePath);
                    } else {
                        state.Listener.Send(state, server.Messages.Get553());
                        return;
                    }

                    if (fso != null && fso.Exists) {
                        state.Listener.Send(state, server.Messages.Get550(Reason550.FileAlreadyExists));
                    } else {
                        if (server.SecurityProvider.CanWrite(state.User, fso)) {
                            state.LastRenameFrom.MoveTo(fso);
                            state.Listener.Send(state, server.Messages.Get250());
                        } else {
                            state.Listener.Send(state, server.Messages.Get550(Reason550.AccessDenied));
                        }
                    }
                }
            }
        }
    }
}
